// 条款47：请使用traits classes表现类型信息
// 核心概念
// Traits classes（特性类）是一种用于在编译期获取和操作类型信息的C++技术。
// 它们提供了一种机制，让我们能够在不修改原有类型的情况下，为这些类型"添加"额外的特性或行为信息。

// 问题背景
// 在泛型编程中，我们经常需要根据类型的特性来调整算法的行为。例如，在实现迭代器时，我们可能需要知道：
// 1.迭代器的类别（随机访问、双向、前向等）
// 2.迭代器指向的值类型
// 3.迭代器的距离类型
// 但这些信息并不总是直接从类型本身可以获取的，尤其是对于内置类型（如指针）。

// Traits Classes 的实现
// Traits classes 通常是模板类，它们为不同的类型提供统一的接口来访问类型相关的信息。
// 标准库中的 std::iterator_traits 是一个典型例子：
template <typename IterT>
struct iterator_traits
{
    typedef typename IterT::iterator_category iterator_category;
    typedef typename IterT::value_type value_type;
    typedef typename IterT::difference_type difference_type;
    typedef typename IterT::pointer pointer;
    typedef typename IterT::reference reference;
};

// 对于指针类型，标准库提供了特化版本：
// 部分特化
template <typename T>
struct iterator_traits<T *>
{
    typedef random_access_iterator_tag iterator_category;
    typedef T value_type;
    typedef ptrdiff_t difference_type;
    typedef T *pointer;
    typedef T &reference;
};

// 使用 Traits Classes
// 以下是一个使用 traits 来实现根据迭代器类型优化 advance 函数的例子
template <typename IterT, typename DistT>
void advance(IterT &iter, DistT d)
{
    // 使用traits获取迭代器类别
    typedef typename std::iterator_traits<IterT>::iterator_category category;

    // 根据迭代器类别调用不同的实现
    _advance(iter, d, category());
}

// 随机访问迭代器的实现
template <typename IterT, typename DistT>
void _advance(IterT &iter, DistT d, std::random_access_iterator_tag)
{
    iter += d; // 常数时间操作
}

// 双向迭代器的实现
template <typename IterT, typename DistT>
void _advance(IterT &iter, DistT d, std::bidirectional_iterator_tag)
{
    if (d >= 0)
    {
        while (d--)
            ++iter; // 线性时间操作
    }
    else
    {
        while (d++)
            --iter;
    }
}

// 前向迭代器的实现
template <typename IterT, typename DistT>
void _advance(IterT &iter, DistT d, std::forward_iterator_tag)
{
    while (d--)
        ++iter; // 线性时间操作，只能前进
}

// Traits Classes 的设计原则
// 1.将信息放在模板参数中：traits classes 通常是模板类，它们的模板参数就是我们想要获取信息的类型。
// 2.提供默认值：对于自定义类型，traits classes 可以从类型本身获取信息；对于内置类型，traits classes 提供特化版本。
// 3.使用类型嵌套：traits classes 通常使用嵌套类型定义（typedef）来表示类型信息。
// 4.使用模板特化：为特定类型提供特化版本的 traits classes，以处理那些没有内部类型定义的类型。

// 实际应用
// 1.除了迭代器traits，标准库还提供了其他类型的traits：
// 2.类型特性（Type Traits）：如 std::is_integral、std::is_floating_point 等，用于在编译期判断类型的特性。
// 3.数值限制（Numeric Limits）：std::numeric_limits 提供了数值类型的各种限制信息，如最大值、最小值等。
// 4.字符特性（Character Traits）：std::char_traits 提供了字符类型的各种操作，如比较、复制等。

// 总结
// 1.Traits classes 是一种在编译期获取和操作类型信息的技术。
// 2.它们允许我们在不修改原有类型的情况下，为这些类型添加额外的信息。
// 3.通过 traits classes，我们可以实现根据类型特性自动选择最优算法的泛型代码。
// 4.标准库中的 std::iterator_traits、std::type_traits 等都是 traits classes 的例子。
// 5.设计良好的 traits classes 应该提供默认实现和特化版本，以处理各种类型。
// 这种技术在现代C++中非常重要，是实现高效泛型编程的关键工具之一。